package de.teamgamma.cansat.groundstation.usb;

import org.json.JSONException;
import org.json.JSONObject;

import jssc.SerialPort;
import jssc.SerialPortException;
import jssc.SerialPortList;

/**
 * Class which starts the serial port connection and received the data
 * @author Alexander Ciupka
 */

public class USB implements Runnable {
	private SerialPort serialPort;
	private String incomingString;
	private String oldString;
	private Receiver receiver;
	public static final int SLEEP_TIME = 500;
	
	/**
	 * Contstructor
	 */
	
	public USB() {
		receiver = Receiver.getInstance();
		oldString = "";
	}
	
	/**
	 * Starts the connection to a serial port
	 */
	
	public void startConnection() {
    	receiver = Receiver.getInstance();
		boolean check = false;
		do {
			String[] ports;
			//do-while loop which searching for serial ports to connect
			do {
				//Save all possible and readable serial ports in an array
				ports = SerialPortList.getPortNames();
				try {
					Thread.sleep(2500);
				} catch (InterruptedException e) {
					System.err.println("It's too early, I can't sleep!");
				}
				System.out.println("Searching for Serial Ports!");
				System.out.println(ports[0]);
			} while(ports.length < 1);
			//Creates a new SerialPort object
			serialPort = new SerialPort(ports[0]);
	    	System.out.println("Serial Port: " + serialPort.getPortName() + " was found!");
	    	try {
	    		//try to open the serial Port
	    		serialPort.openPort();
	    		//set the BAUDRate, Databits and Stopbits
	    		serialPort.setParams(SerialPort.BAUDRATE_9600, SerialPort.DATABITS_8, SerialPort.STOPBITS_1, SerialPort.PARITY_NONE);
	        	serialPort.setRTS(false);
	        	check = true;
	    	} 
	    	catch (SerialPortException e) {
	    		System.err.println("Cannot open Serial Port!");
	    	}
		} while(!check);
		System.out.println("Connection to Serial Port: " + serialPort.getPortName() + " was succesful!");
	}
    
	/**
	 * reads from the opened serial port and sends the received json to the receiver
	 */
	
    public void receiveJSON() {
    	incomingString = null;
    	boolean check = false;
	    try {
	    	//Trying to read from the serial port
	       	incomingString = serialPort.readString();
	    }
	    catch (Exception ex) { 
		   	System.err.println("Cannot read from the Serial Port!");
	    }
       	if (incomingString != null) {
       		if(incomingString.contains("}")) {
       			//splitting the received json
	       		String[] splitString = incomingString.split("}");
	       		incomingString = splitString[0] + "}";
	       		try {
	       			//Trying to create a json with the older jsonstring and the received jsonstring
	       			new JSONObject(oldString + incomingString);
	       			incomingString = oldString + incomingString;
	       			check = true;
	       		}
	       		catch(JSONException j) {
	       			try {
	       				//trying to create a json with the received json
	       				new JSONObject(incomingString);
	       				check = true;
	       			} catch(JSONException e) {
 	       				System.err.println("Cannot build a correct JSON!");
 	       				check = false;
	       			}
	       		}
	       		if(check)
       				receiver.receiveData(new JSONObject(incomingString));	       
       			if (splitString.length > 1) 
       				oldString = splitString[1];
       			else
       				oldString = "";
       		}
       		else {
       			oldString = incomingString;
       		}
       	}
    }
    
    /**
     * Run method which call the startConnection method and try to call the receiveJSON methode every SLEEP_TIME milliseconds
     */
    
    @Override
	public void run() {
    	startConnection();
    	//endless loop which will trying to receive every SLEEP_TIME ms a json
    	while(true) {
			receiveJSON();
			try {
				Thread.sleep(SLEEP_TIME);
			} catch (InterruptedException e) {
				System.err.println("It's too early, I can't sleep!");
			}
		}
	}
}